package com.zhiwen.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhiwen.common.exception.BusinessException;
import com.zhiwen.domain.dto.QuestionVoteDTO;
import com.zhiwen.domain.entity.Question;
import com.zhiwen.domain.entity.QuestionVote;
import com.zhiwen.mapper.QuestionVoteMapper;
import com.zhiwen.service.QuestionService;
import com.zhiwen.service.QuestionVoteService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;

/**
 * 问题点赞服务实现类
 */
@Service
@RequiredArgsConstructor
public class QuestionVoteServiceImpl extends ServiceImpl<QuestionVoteMapper, QuestionVote> implements QuestionVoteService {

    private final QuestionService questionService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean voteQuestion(QuestionVoteDTO voteDTO) {
        // 获取当前登录用户
        Long userId = StpUtil.getLoginIdAsLong();

        // 检查问题是否存在
        Question question = questionService.getById(voteDTO.getQuestionId());
        if (question == null) {
            throw new BusinessException("问题不存在");
        }

        // 不能给自己的问题点赞
        if (userId.equals(question.getUserId())) {
            throw new BusinessException("不能给自己的问题点赞");
        }

        // 检查是否已经点赞
        LambdaQueryWrapper<QuestionVote> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(QuestionVote::getUserId, userId);
        wrapper.eq(QuestionVote::getQuestionId, voteDTO.getQuestionId());
        wrapper.eq(QuestionVote::getDeleted, 0);
        QuestionVote questionVote = getOne(wrapper);

        int voteChange = 0;

        if (questionVote != null) {
            // 已经点过赞，判断是否是相同的点赞类型
            if (questionVote.getVoteType().equals(voteDTO.getVoteType())) {
                // 相同类型，取消点赞
                questionVote.setDeleted(1);
                updateById(questionVote);

                // 更改点赞状态统计
                if (voteDTO.getVoteType() == 1) {
                    voteChange = -1; // 减少一个赞成票
                } else {
                    voteChange = 1; // 减少一个反对票，实际是增加一个赞成票
                }
            } else {
                // 不同类型，更新点赞类型
                questionVote.setVoteType(voteDTO.getVoteType());
                questionVote.setUpdateTime(LocalDateTime.now());
                updateById(questionVote);

                // 更新点赞数
                if (voteDTO.getVoteType() == 1) {
                    voteChange = 2; // 从反对变为赞成，净增加2票
                } else {
                    voteChange = -2; // 从赞成变为反对，净减少2票
                }
            }
        } else {
            // 未点赞，创建点赞记录
            questionVote = new QuestionVote();
            questionVote.setUserId(userId);
            questionVote.setQuestionId(voteDTO.getQuestionId());
            questionVote.setVoteType(voteDTO.getVoteType());
            questionVote.setCreateTime(LocalDateTime.now());
            questionVote.setUpdateTime(LocalDateTime.now());
            questionVote.setDeleted(0);
            save(questionVote);

            // 更新点赞数
            if (voteDTO.getVoteType() == 1) {
                voteChange = 1; // 增加一个赞成票
            } else {
                voteChange = -1; // 增加一个反对票，实际是减少一个赞成票
            }
        }

        // 更新问题的点赞数
        if (voteChange != 0) {
            // 初始化voteCount，防止空指针
            if (question.getVoteCount() == null) {
                question.setVoteCount(0);
            }
            question.setVoteCount(question.getVoteCount() + voteChange);
            questionService.updateById(question);
        }

        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean cancelVote(Long questionId) {
        // 获取当前登录用户
        Long userId = StpUtil.getLoginIdAsLong();

        // 检查问题是否存在
        Question question = questionService.getById(questionId);
        if (question == null) {
            throw new BusinessException("问题不存在");
        }

        // 查询点赞记录
        LambdaQueryWrapper<QuestionVote> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(QuestionVote::getUserId, userId);
        wrapper.eq(QuestionVote::getQuestionId, questionId);
        wrapper.eq(QuestionVote::getDeleted, 0);
        QuestionVote questionVote = getOne(wrapper);

        if (questionVote == null) {
            return false;
        }

        // 逻辑删除点赞记录
        questionVote.setDeleted(1);
        updateById(questionVote);

        // 更新问题的点赞数
        int voteChange = questionVote.getVoteType() == 1 ? -1 : 1;

        // 初始化voteCount，防止空指针
        if (question.getVoteCount() == null) {
            question.setVoteCount(0);
        }
        question.setVoteCount(question.getVoteCount() + voteChange);
        questionService.updateById(question);

        return true;
    }

    @Override
    public Integer checkVoteStatus(Long questionId) {
        // 获取当前登录用户
        Long userId = StpUtil.getLoginIdAsLong();

        // 查询点赞记录
        LambdaQueryWrapper<QuestionVote> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(QuestionVote::getUserId, userId);
        wrapper.eq(QuestionVote::getQuestionId, questionId);
        wrapper.eq(QuestionVote::getDeleted, 0);
        QuestionVote questionVote = getOne(wrapper);

        return questionVote != null ? questionVote.getVoteType() : null;
    }
}
